package cn.springcloud.fix.common.log.aspect;

import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import cn.springcloud.fix.common.core.utils.IpUtil;
import cn.springcloud.fix.common.core.utils.WebUtil;
import cn.springcloud.fix.common.log.annotation.AsyncLog;
import cn.springcloud.fix.common.log.entity.SysLogVO;
import cn.springcloud.fix.common.core.enums.BusinessStatus;
import cn.springcloud.fix.common.log.event.SysOpLogEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

@Slf4j
@Aspect
public class AsyncLogAspect {

    @Autowired
    private ApplicationEventPublisher publisher;

    @Pointcut("@annotation(cn.springcloud.fix.common.log.annotation.AsyncLog)")
    public void pointCut() {
    }

    @Before("@annotation(cn.springcloud.fix.common.log.annotation.AsyncLog)")
    public void before(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        AsyncLog asyncLog = method.getAnnotation(AsyncLog.class);
        log.info("AsyncLog注解的value：{}", asyncLog.value());
    }

    /*@Around("@annotation(asyncLog)")
    public Object around(ProceedingJoinPoint point, AsyncLog asyncLog) throws Throwable {

    }*/

    @AfterReturning(pointcut = "pointCut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        this.handleLog(joinPoint, null);
    }

    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        this.handleLog(joinPoint, e);
    }

    private void handleLog(final JoinPoint joinPoint, final Exception ex) {
        try {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            AsyncLog asyncLog = method.getAnnotation(AsyncLog.class);
            if (asyncLog == null) return;

//            HttpServletRequest servletRequest = WebUtil.getRequest();
//            SysOperateLogRequest request = new SysOperateLogRequest();
//            request.setStatus(BusinessStatus.SUCCESS.ordinal());
//            String ip = IpUtil.getIP();
//            request.setIp(ip);
//            request.setUrl(servletRequest.getRequestURI());
//            // String username = request.getHeader("username");
//            // request.setOperName(username);
//            if (ex != null) {
//                request.setStatus(BusinessStatus.FAIL.ordinal());
//                request.setErrorMsg(StringUtils.substring(ex.getMessage(), 0, 2000));
//            }
//            // 设置方法名称
//            String className = joinPoint.getTarget().getClass().getName();
//            String methodName = joinPoint.getSignature().getName();
//            request.setMethod(className + "." + methodName + "()");
//            request.setRequestMethod(request.getMethod());
//            // 处理设置注解上的参数
//            Object[] args = joinPoint.getArgs();
//            // 发布事件
//            publisher.publishEvent(new SysOpLogEvent(request));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private SysLogVO assembleLogVO() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        SysLogVO sysLog = new SysLogVO();
        sysLog.setCreateBy("yang jun");
        sysLog.setType("0");
        sysLog.setRemoteAddr(ServletUtil.getClientIP(request));
        sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
        sysLog.setMethod(request.getMethod());
        sysLog.setUserAgent(request.getHeader("user-agent"));
        sysLog.setParams(HttpUtil.toParams(request.getParameterMap()));
        sysLog.setServiceId(null);
        return sysLog;
    }
}
